package com.toocms.jinjuhang.widget.decoration

import android.content.Context
import android.graphics.Canvas
import android.graphics.Paint
import android.graphics.Rect
import android.graphics.drawable.Drawable
import android.os.Build
import android.view.View
import androidx.annotation.ColorInt
import androidx.annotation.DrawableRes
import androidx.annotation.IdRes
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import me.jessyan.autosize.utils.AutoSizeUtils
import java.lang.IllegalArgumentException

class TimerShaftDecoration(private val mContext: Context) : RecyclerView.ItemDecoration() {
    private var mGravity = Gravity.CENTER //所化的时间轴重力方向
    private var mTimerShaftWidth = WHITE_WRAP_CONTENT //时间轴整体所占宽度(单位dp)

    @DrawableRes
    private var mDefaultTimeDotResId = 0 //默认时间点样式

    @DrawableRes
    private var mCurrentTimeDotResId = 0 //当前时间点样式
    val mDefaultTimeDotWidth = 8 //默认的时间点宽度
    private var mTimerShaftLineColor = -0x666667 //时间轴线颜色
    private var mTimerShaftLineWidth = 2 //时间轴线宽度(单位dp)
    private var mLineAndDotInterval = 0 //线和时间点的间隔距离(单位dp)
    private var mOffset = 0 //与重力方向的偏移(Gravity.CENTER:为左边的偏移量)

    @IdRes
    private var mAligningViewId = 0
    private val noDefaultDotResDotColor = -0x666667
    private val noCurrentDotResDotColor = -0x10000
    val defaultBackgroundColor = 0x00000000 //默认背景色
    private var isLineExceedDot = true
    private var mDotPaint: Paint? = null
    private var mLinePaint: Paint? = null
    private var mBackgroundPaint: Paint? = null
    private var mCurrentDotPosition = -1 //当前时间点
    private var startDrawPosition = 0 //开始绘制的位置

    init {
        initializePaint()
    }

    private fun initializePaint() {
        mDotPaint = Paint()
        mLinePaint = Paint()
        mBackgroundPaint = Paint()
        mBackgroundPaint!!.color = defaultBackgroundColor
    }

    override fun onDraw(c: Canvas, parent: RecyclerView, state: RecyclerView.State) {
        super.onDraw(c, parent, state)
        val layoutManager = parent.layoutManager
        require(!(layoutManager !is LinearLayoutManager || layoutManager is GridLayoutManager)) { "不支持该布局管理器:" + layoutManager!!.javaClass.name }
        val linearLayoutManager = layoutManager
        val itemCount = parent.adapter!!.itemCount
        val count = parent.childCount
        for (i in 0 until count) {
            val itemView = parent.getChildAt(i)
            val layoutPosition = parent.getChildLayoutPosition(itemView)
            if (startDrawPosition > layoutPosition) {
                continue
            }
            if (LinearLayoutManager.VERTICAL == linearLayoutManager.orientation) {
                verticalDraw(c, linearLayoutManager, itemView, itemCount, layoutPosition)
            } else {
                horizontalDraw(c, linearLayoutManager, itemView, itemCount, layoutPosition)
            }
        }
    }

    private fun horizontalDraw(
        c: Canvas,
        layoutManager: LinearLayoutManager,
        itemView: View,
        itemCount: Int,
        position: Int
    ) {
        val decoratedLeft = layoutManager.getDecoratedLeft(itemView)
        val decoratedRight = layoutManager.getDecoratedRight(itemView)
        val itemViewLeft = itemView.left
        val itemViewRight = itemView.right
        mLinePaint!!.color = mTimerShaftLineColor
        var dot: Drawable? = null
        dot = if (mCurrentDotPosition == position) {
            getTimeDot(mCurrentTimeDotResId)
        } else {
            getTimeDot(mDefaultTimeDotResId)
        }
        val aligningCenterX: Int
        aligningCenterX = if (0 == mAligningViewId || null == itemView.findViewById(
                mAligningViewId
            )
        ) {
            (itemViewLeft + itemViewRight) / 2
        } else {
            val aligningView = itemView.findViewById<View>(mAligningViewId)
            itemViewLeft + (aligningView.left + aligningView.right) / 2
        }
        //绘制背景
        var backgroundLeft = layoutManager.getDecoratedLeft(itemView)
        val backgroundTop = layoutManager.getDecoratedTop(itemView)
        var backgroundRight = layoutManager.getDecoratedLeft(itemView)
        val backgroundBottom = itemView.top
        if (startDrawPosition == position && !isLineExceedDot) {
            backgroundLeft = itemView.left
        }
        if (1 == itemCount - position && !isLineExceedDot) {
            backgroundRight = itemView.right
        }
        c.drawRect(
            backgroundLeft.toFloat(),
            backgroundTop.toFloat(),
            backgroundRight.toFloat(),
            backgroundBottom.toFloat(),
            mBackgroundPaint!!
        )
        //绘制点
        val dotCentreY: Int //点中心点的Y坐标
        val dotLeft: Int //点的左边
        val dotRight: Int //点的右边
        if (null == dot) {
            mDotPaint!!.color =
                if (mCurrentDotPosition == position) noCurrentDotResDotColor else noDefaultDotResDotColor
            dotCentreY =
                if (Gravity.LEFT == mGravity) {
                    dp2px(mOffset) + dp2px(mDefaultTimeDotWidth) / 2
                } else if (Gravity.RIGHT == mGravity) {
                    timerShaftWidth - dp2px(mOffset) - dp2px(mDefaultTimeDotWidth) / 2
                } else {
                    timerShaftWidth / 2 + dp2px(mOffset) - dp2px(mDefaultTimeDotWidth) / 2
                }
            dotLeft = aligningCenterX - dp2px(mDefaultTimeDotWidth) / 2
            dotRight = aligningCenterX + dp2px(mDefaultTimeDotWidth) / 2
            c.drawCircle(
                aligningCenterX.toFloat(),
                dotCentreY.toFloat(),
                (dp2px(mDefaultTimeDotWidth) / 2).toFloat(),
                mDotPaint!!
            )
        } else {
            dot.setBounds(0, 0, dot.intrinsicWidth, dot.intrinsicHeight)
            val top: Int
            val left = aligningCenterX - dot.intrinsicWidth / 2
            dotLeft = left
            dotRight = left + dot.intrinsicWidth
            top =
                if (Gravity.LEFT == mGravity) {
                    dp2px(mOffset) + (maxTimeDotHeight - dot.intrinsicHeight) / 2
                } else if (Gravity.RIGHT == mGravity) {
                    timerShaftHeight - dp2px(mOffset) - maxTimeDotHeight + (maxTimeDotHeight - dot.intrinsicHeight) / 2
                } else {
                    timerShaftHeight / 2 + dp2px(mOffset) - maxTimeDotHeight / 2 + (maxTimeDotHeight - dot.intrinsicHeight) / 2
                }
            dotCentreY = top + dot.intrinsicHeight / 2
            c.save()
            c.translate(left.toFloat(), top.toFloat())
            dot.draw(c)
            c.restore()
        }
        mLinePaint!!.color = mTimerShaftLineColor
        val lineTop = dotCentreY - dp2px(mTimerShaftLineWidth) / 2
        val lineBottom = dotCentreY + dp2px(mTimerShaftLineWidth) / 2
        var lineLeft: Int
        var lineRight: Int
        //绘制点左边的线
        if (startDrawPosition != position || isLineExceedDot) {
            lineLeft = decoratedLeft
            lineRight = dotLeft - dp2px(mLineAndDotInterval)
            c.drawRect(
                lineLeft.toFloat(),
                lineTop.toFloat(),
                lineRight.toFloat(),
                lineBottom.toFloat(),
                mLinePaint!!
            )
        }
        //绘制点右边的线
        if (1 != itemCount - position || isLineExceedDot) {
            lineLeft = dotRight + dp2px(mLineAndDotInterval)
            lineRight = decoratedRight
            c.drawRect(
                lineLeft.toFloat(),
                lineTop.toFloat(),
                lineRight.toFloat(),
                lineBottom.toFloat(),
                mLinePaint!!
            )
        }
    }

    private fun verticalDraw(
        c: Canvas,
        layoutManager: LinearLayoutManager,
        itemView: View,
        itemCount: Int,
        position: Int
    ) {
        val decoratedTop = layoutManager.getDecoratedTop(itemView)
        val decoratedBottom = layoutManager.getDecoratedBottom(itemView)
        val itemViewTop = itemView.top
        val itemViewBottom = itemView.bottom
        mLinePaint!!.color = mTimerShaftLineColor
        var dot: Drawable? = null
        dot = if (mCurrentDotPosition == position) {
            getTimeDot(mCurrentTimeDotResId)
        } else {
            getTimeDot(mDefaultTimeDotResId)
        }
        val aligningCenterY: Int
        aligningCenterY = if (0 == mAligningViewId || null == itemView.findViewById(
                mAligningViewId
            )
        ) {
            (itemViewTop + itemViewBottom) / 2
        } else {
            val aligningView = itemView.findViewById<View>(mAligningViewId)
            itemViewTop + (aligningView.top + aligningView.bottom) / 2
        }
        //绘制背景
        val backgroundLeft = layoutManager.getDecoratedLeft(itemView)
        var backgroundTop = layoutManager.getDecoratedTop(itemView)
        val backgroundRight = itemView.left
        var backgroundBottom = layoutManager.getDecoratedBottom(itemView)
        if (startDrawPosition == position && !isLineExceedDot) {
            backgroundTop = itemView.top
        }
        if (1 == itemCount - position && !isLineExceedDot) {
            backgroundBottom = itemView.bottom
        }
        c.drawRect(
            backgroundLeft.toFloat(),
            backgroundTop.toFloat(),
            backgroundRight.toFloat(),
            backgroundBottom.toFloat(),
            mBackgroundPaint!!
        )
        //绘制点
        val dotCentreX: Int //点中心点的X坐标
        val dotTop: Int //点的顶部
        val dotBottom: Int //点的底部
        if (null == dot) {
            mDotPaint!!.color =
                if (mCurrentDotPosition == position) noCurrentDotResDotColor else noDefaultDotResDotColor
            dotCentreX =
                if (Gravity.LEFT == mGravity) {
                    dp2px(mOffset) + dp2px(mDefaultTimeDotWidth) / 2
                } else if (Gravity.RIGHT == mGravity) {
                    timerShaftWidth - dp2px(mOffset) - dp2px(mDefaultTimeDotWidth) / 2
                } else {
                    timerShaftWidth / 2 + dp2px(mOffset) - dp2px(mDefaultTimeDotWidth) / 2
                }
            dotTop = aligningCenterY - dp2px(mDefaultTimeDotWidth) / 2
            dotBottom = aligningCenterY + dp2px(mDefaultTimeDotWidth) / 2
            c.drawCircle(
                dotCentreX.toFloat(),
                aligningCenterY.toFloat(),
                (dp2px(mDefaultTimeDotWidth) / 2).toFloat(),
                mDotPaint!!
            )
        } else {
            dot.setBounds(0, 0, dot.intrinsicWidth, dot.intrinsicHeight)
            val left: Int
            val top = aligningCenterY - dot.intrinsicHeight / 2
            dotTop = top
            dotBottom = top + dot.intrinsicHeight
            left =
                if (Gravity.LEFT == mGravity) {
                    dp2px(mOffset) + (maxTimeDotWidth - dot.intrinsicWidth) / 2
                } else if (Gravity.RIGHT == mGravity) {
                    timerShaftWidth - dp2px(mOffset) - maxTimeDotWidth + (maxTimeDotWidth - dot.intrinsicWidth) / 2
                } else {
                    timerShaftWidth / 2 + dp2px(mOffset) - maxTimeDotWidth / 2 + (maxTimeDotWidth - dot.intrinsicWidth) / 2
                }
            dotCentreX = left + dot.intrinsicWidth / 2
            c.save()
            c.translate(left.toFloat(), top.toFloat())
            dot.draw(c)
            c.restore()
        }
        mLinePaint!!.color = mTimerShaftLineColor
        val lineLeft = dotCentreX - dp2px(mTimerShaftLineWidth) / 2
        val lineRight = dotCentreX + dp2px(mTimerShaftLineWidth) / 2
        var lineTop: Int
        var lineBottom: Int
        //绘制点上边的线
        if (startDrawPosition != position || isLineExceedDot) {
            lineTop = decoratedTop
            lineBottom = dotTop - dp2px(mLineAndDotInterval)
            c.drawRect(
                lineLeft.toFloat(),
                lineTop.toFloat(),
                lineRight.toFloat(),
                lineBottom.toFloat(),
                mLinePaint!!
            )
        }
        //绘制点下边的线
        if (1 != itemCount - position || isLineExceedDot) {
            lineTop = dotBottom + dp2px(mLineAndDotInterval)
            lineBottom = decoratedBottom
            c.drawRect(
                lineLeft.toFloat(),
                lineTop.toFloat(),
                lineRight.toFloat(),
                lineBottom.toFloat(),
                mLinePaint!!
            )
        }
    }

    override fun getItemOffsets(
        outRect: Rect,
        view: View,
        parent: RecyclerView,
        state: RecyclerView.State
    ) {
        super.getItemOffsets(outRect, view, parent, state)
        val layoutManager = parent.layoutManager
        require(layoutManager is LinearLayoutManager) { "不支持该布局管理器:" + layoutManager!!.javaClass.name }
        val layoutPosition = parent.getChildLayoutPosition(view)
        if (startDrawPosition > layoutPosition) {
            return
        }
        if (LinearLayoutManager.VERTICAL == layoutManager.orientation) {
            verticalItemOffsets(outRect, view, parent, state)
        } else {
            horizontalItemOffsets(outRect, view, parent, state)
        }
    }

    private fun horizontalItemOffsets(
        outRect: Rect,
        view: View,
        parent: RecyclerView,
        state: RecyclerView.State
    ) {
        outRect.top = timerShaftHeight
    }

    private fun verticalItemOffsets(
        outRect: Rect,
        view: View,
        parent: RecyclerView,
        state: RecyclerView.State
    ) {
        outRect.left = timerShaftWidth
    }

    /**
     * 设置当前时间点资源
     *
     * @param currentTimeDotRes 资源文件Id(必须有固定宽高)
     */
    fun setCurrentTimeDotRes(@DrawableRes currentTimeDotRes: Int) {
        checkDrawable(currentTimeDotRes)
        mCurrentTimeDotResId = currentTimeDotRes
    }

    /**
     * 设置默认时间点资源
     *
     * @param defaultTimeDotRes 资源文件Id(必须有固定宽高)
     */
    fun setDefaultTimeDotRes(@DrawableRes defaultTimeDotRes: Int) {
        checkDrawable(defaultTimeDotRes)
        mDefaultTimeDotResId = defaultTimeDotRes
    }

    /**
     * 设置重力方向
     *
     * @param gravity
     */
    fun setGravity(gravity: Gravity) {
        mGravity = gravity
    }

    /**
     * 设置时间轴线的颜色
     *
     * @param timerShaftLineColor
     */
    fun setTimerShaftLineColor(@ColorInt timerShaftLineColor: Int) {
        mTimerShaftLineColor = timerShaftLineColor
    }

    /**
     * 设置偏移
     *
     * @param offset
     */
    fun setOffset(offset: Int) {
        mOffset = offset
    }

    fun setStartDrawPosition(startDrawPosition: Int) {
        this.startDrawPosition = startDrawPosition
    }

    /**
     * 设置背景颜色
     * @param backgroundColor
     */
    fun setBackgroundColor(@ColorInt backgroundColor: Int) {
        mBackgroundPaint!!.color = backgroundColor
    }

    /**
     * 设置时间轴线的宽度
     *
     * @param timerShaftLineWidth
     */
    fun setTimerShaftLineWidth(timerShaftLineWidth: Int) {
        mTimerShaftLineWidth = timerShaftLineWidth
    }

    /**
     * 设置线是否超过首尾两个点
     *
     * @param isLineExceedDot
     */
    fun setLineExceedDot(isLineExceedDot: Boolean) {
        this.isLineExceedDot = isLineExceedDot
    }

    /**
     * 设置当前时间点的位置
     *
     * @param currentDotPosition
     */
    fun setCurrentDotPosition(currentDotPosition: Int) {
        mCurrentDotPosition = currentDotPosition
    }

    /**
     * 设置点和线之间的间隔
     *
     * @param lineAndDotInterval
     */
    fun setLineAndDotInterval(lineAndDotInterval: Int) {
        mLineAndDotInterval = lineAndDotInterval
    }

    /**
     * 时间点对齐的View
     *
     * @param aligningViewId 要对齐的控件Id
     */
    fun setAligningViewId(aligningViewId: Int) {
        mAligningViewId = aligningViewId
    }
    /**
     * 获取时间轴整体宽度
     *
     * @return
     */
    /**
     * 设置时间轴的宽度
     *
     * @param timerShaftWidth
     */
    var timerShaftWidth: Int
        get() {
            var result = 0
            val maxTimeDotWidth = maxTimeDotWidth
            if (WHITE_WRAP_CONTENT == mTimerShaftWidth) {
                result = maxTimeDotWidth
            } else {
                result = dp2px(mTimerShaftWidth)
                if (result < maxTimeDotWidth) {
                    result = maxTimeDotWidth
                }
            }
            return result
        }
        set(timerShaftWidth) {
            var timerShaftWidth = timerShaftWidth
            if (0 >= timerShaftWidth) {
                timerShaftWidth = WHITE_WRAP_CONTENT
            }
            mTimerShaftWidth = timerShaftWidth
        }

    /**
     * 获取时间轴整体宽度
     *
     * @return
     */
    private val timerShaftHeight: Int
        private get() {
            var result = 0
            val maxTimeDotHight = maxTimeDotHeight
            if (WHITE_WRAP_CONTENT == mTimerShaftWidth) {
                result = maxTimeDotHight
            } else {
                result = dp2px(mTimerShaftWidth)
                if (result < maxTimeDotHight) {
                    result = maxTimeDotHight
                }
            }
            return result
        }

    /**
     * 获取时间点最大的宽度
     *
     * @return
     */
    private val maxTimeDotWidth: Int
        private get() {
            val defaultTimeDotRes = getTimeDot(mDefaultTimeDotResId)
            val currentTimeDotRes = getTimeDot(mCurrentTimeDotResId)
            var defaultTimeDotWidth = dp2px(mDefaultTimeDotWidth)
            var currentTimeDotWidth = dp2px(mDefaultTimeDotWidth)
            if (null != defaultTimeDotRes) {
                defaultTimeDotWidth = defaultTimeDotRes.intrinsicWidth
            }
            if (null != currentTimeDotRes) {
                currentTimeDotWidth = currentTimeDotRes.intrinsicWidth
            }
            return if (defaultTimeDotWidth > currentTimeDotWidth) defaultTimeDotWidth else currentTimeDotWidth
        }

    /**
     * 获取时间点最大的高度
     *
     * @return
     */
    private val maxTimeDotHeight: Int
        private get() {
            val defaultTimeDotRes = getTimeDot(mDefaultTimeDotResId)
            val currentTimeDotRes = getTimeDot(mCurrentTimeDotResId)
            var defaultTimeDotWidth = dp2px(mDefaultTimeDotWidth)
            var currentTimeDotWidth = dp2px(mDefaultTimeDotWidth)
            if (null != defaultTimeDotRes) {
                defaultTimeDotWidth = defaultTimeDotRes.intrinsicHeight
            }
            if (null != currentTimeDotRes) {
                currentTimeDotWidth = currentTimeDotRes.intrinsicHeight
            }
            return if (defaultTimeDotWidth > currentTimeDotWidth) defaultTimeDotWidth else currentTimeDotWidth
        }

    private fun checkDrawable(@DrawableRes resId: Int) {
        val timeDot = getTimeDot(resId)
        if (0 >= timeDot!!.intrinsicWidth || 0 >= timeDot.intrinsicHeight) {
            val resourceName = mContext.resources.getResourceName(resId)
            throw IllegalArgumentException("所设置资源(" + resourceName + ")没有设置size(width:" + timeDot.intrinsicWidth + " height:" + timeDot.intrinsicHeight + ")")
        }
    }

    private fun getTimeDot(@DrawableRes dotResId: Int): Drawable? {
        val resources = mContext.resources
        var result: Drawable? = null
        if (0 != dotResId) {
            result = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                resources.getDrawable(dotResId, mContext.theme)
            } else {
                resources.getDrawable(dotResId)
            }
        }
        return result
    }

    private fun dp2px(dp: Int): Int {
        return AutoSizeUtils.dp2px(mContext, dp.toFloat())
    }

    enum class Gravity {
        LEFT, CENTER, RIGHT
    }

    companion object {
        const val WHITE_WRAP_CONTENT = -1 //宽度自适应
    }
}